using AuthService.Domain.Entities;
using AuthService.Domain.Repositories;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Reflection;
using System.Text.Json;

namespace AuthService.Application.Services;

/// <summary>
/// 动态API映射服务实现
/// 自动将服务层方法映射为动态API端点
/// </summary>
public class DynamicApiMappingService : IDynamicApiMappingService
{
    private readonly IDynamicApiEndpointRepository _endpointRepository;
    private readonly ILogger<DynamicApiMappingService> _logger;
    private readonly DynamicApiMappingOptions _options;
    private readonly IServiceProvider _serviceProvider;

    public DynamicApiMappingService(
        IDynamicApiEndpointRepository endpointRepository,
        ILogger<DynamicApiMappingService> logger,
        IOptions<DynamicApiMappingOptions> options,
        IServiceProvider serviceProvider)
    {
        _endpointRepository = endpointRepository;
        _logger = logger;
        _options = options.Value;
        _serviceProvider = serviceProvider;
    }

    /// <summary>
    /// 初始化动态API映射（自动发现模式）
    /// </summary>
    public async Task<int> InitializeMappingsAsync(CancellationToken cancellationToken = default)
    {
        try
        {
            _logger.LogInformation("开始自动发现并初始化动态API映射...");

            var createdCount = 0;

            // 自动发现所有服务并创建端点
            createdCount += await AutoDiscoverAndCreateEndpointsAsync(cancellationToken);

            _logger.LogInformation("动态API映射初始化完成，共创建 {Count} 个端点", createdCount);
            return createdCount;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "初始化动态API映射失败");
            throw;
        }
    }

    /// <summary>
    /// 自动发现服务并创建API端点
    /// </summary>
    private async Task<int> AutoDiscoverAndCreateEndpointsAsync(CancellationToken cancellationToken = default)
    {
        var createdCount = 0;

        // 定义要自动发现的服务接口
        var serviceTypes = new[]
        {
            typeof(IUserService),
            typeof(ITestService)  // 添加测试服务
        };

        foreach (var serviceType in serviceTypes)
        {
            var serviceName = serviceType.Name.TrimStart('I'); // 移除接口前缀I
            var pathPrefix = serviceName.ToLowerInvariant().Replace("service", ""); // 生成路径前缀

            _logger.LogInformation("自动发现服务: {ServiceType}, 路径前缀: {PathPrefix}", serviceType.Name, pathPrefix);

            var endpoints = await CreateServiceEndpointsAsync(serviceType, pathPrefix, cancellationToken);
            createdCount += endpoints.Count();
        }

        return createdCount;
    }

    /// <summary>
    /// 为指定服务创建动态API端点
    /// </summary>
    public async Task<IEnumerable<DynamicApiEndpoint>> CreateServiceEndpointsAsync<TService>(
        string servicePrefix,
        CancellationToken cancellationToken = default) where TService : class
    {
        try
        {
            _logger.LogInformation("为服务 {ServiceType} 创建动态API端点，前缀: {Prefix}",
                typeof(TService).Name, servicePrefix);

            var endpoints = new List<DynamicApiEndpoint>();
            var serviceType = typeof(TService);
            var methods = serviceType.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                .Where(m => ShouldIncludeMethod(m))
                .ToList();

            foreach (var method in methods)
            {
                var mapping = CreateMethodMapping(method, servicePrefix);
                var endpoint = await CreateEndpointFromMapping(mapping, serviceType.Name, cancellationToken);

                if (endpoint != null)
                {
                    endpoints.Add(endpoint);
                }
            }

            _logger.LogInformation("为服务 {ServiceType} 创建了 {Count} 个端点",
                typeof(TService).Name, endpoints.Count);

            return endpoints;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "为服务 {ServiceType} 创建端点失败", typeof(TService).Name);
            throw;
        }
    }

    /// <summary>
    /// 为指定服务创建动态API端点（Type版本）
    /// </summary>
    public async Task<IEnumerable<DynamicApiEndpoint>> CreateServiceEndpointsAsync(
        Type serviceType,
        string servicePrefix,
        CancellationToken cancellationToken = default)
    {
        try
        {
            _logger.LogInformation("为服务 {ServiceType} 创建动态API端点，前缀: {Prefix}",
                serviceType.Name, servicePrefix);

            var endpoints = new List<DynamicApiEndpoint>();
            var methods = serviceType.GetMethods(BindingFlags.Public | BindingFlags.Instance)
                .Where(m => ShouldIncludeMethod(m))
                .ToList();

            foreach (var method in methods)
            {
                var mapping = CreateMethodMapping(method, servicePrefix);
                var endpoint = await CreateEndpointFromMapping(mapping, serviceType.Name, cancellationToken);

                if (endpoint != null)
                {
                    endpoints.Add(endpoint);
                }
            }

            _logger.LogInformation("为服务 {ServiceType} 创建了 {Count} 个端点",
                serviceType.Name, endpoints.Count);

            return endpoints;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "为服务 {ServiceType} 创建端点失败", serviceType.Name);
            throw;
        }
    }

    /// <summary>
    /// 刷新动态API映射
    /// </summary>
    public async Task<int> RefreshMappingsAsync(CancellationToken cancellationToken = default)
    {
        try
        {
            _logger.LogInformation("开始刷新动态API映射...");

            // 删除现有的自动生成的端点
            var existingEndpoints = await _endpointRepository.GetAllAsync(null, cancellationToken);
            var autoGeneratedEndpoints = existingEndpoints.Where(e =>
                e.Tags.Contains("auto-generated")).ToList();

            foreach (var endpoint in autoGeneratedEndpoints)
            {
                await _endpointRepository.DeleteAsync(endpoint.Id, "system", cancellationToken);
            }

            // 重新创建端点
            var createdCount = await InitializeMappingsAsync(cancellationToken);

            _logger.LogInformation("动态API映射刷新完成，删除 {DeletedCount} 个端点，创建 {CreatedCount} 个端点",
                autoGeneratedEndpoints.Count, createdCount);

            return createdCount;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "刷新动态API映射失败");
            throw;
        }
    }

    /// <summary>
    /// 获取所有动态API端点
    /// </summary>
    public async Task<IEnumerable<DynamicApiEndpoint>> GetAllEndpointsAsync(CancellationToken cancellationToken = default)
    {
        return await _endpointRepository.GetAllAsync(null, cancellationToken);
    }

    /// <summary>
    /// 根据路径和方法查找API端点
    /// </summary>
    public async Task<DynamicApiEndpoint?> FindEndpointAsync(
        string path,
        string method,
        CancellationToken cancellationToken = default)
    {
        var endpoints = await _endpointRepository.GetByPathAndMethodAsync(path, method, null, cancellationToken);
        return endpoints.FirstOrDefault(e => e.IsEnabled);
    }

    /// <summary>
    /// 启用或禁用API端点
    /// </summary>
    public async Task<bool> ToggleEndpointAsync(
        Guid endpointId,
        bool isEnabled,
        CancellationToken cancellationToken = default)
    {
        try
        {
            var endpoint = await _endpointRepository.GetByIdAsync(endpointId, cancellationToken);
            if (endpoint == null)
            {
                return false;
            }

            endpoint.IsEnabled = isEnabled;
            endpoint.UpdatedAt = DateTime.UtcNow;

            await _endpointRepository.UpdateAsync(endpoint, cancellationToken);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "切换端点状态失败: {EndpointId}", endpointId);
            return false;
        }
    }

    /// <summary>
    /// 判断是否应该包含该方法
    /// </summary>
    private bool ShouldIncludeMethod(MethodInfo method)
    {
        // 排除特殊方法
        if (_options.ExcludedMethodPatterns.Any(pattern =>
            IsMethodNameMatch(method.Name, pattern)))
        {
            return false;
        }

        // 只包含匹配的方法
        if (_options.IncludedMethodPatterns.Any() &&
            !_options.IncludedMethodPatterns.Any(pattern =>
                IsMethodNameMatch(method.Name, pattern)))
        {
            return false;
        }

        // 排除非公共方法
        if (!method.IsPublic)
        {
            return false;
        }

        // 排除静态方法
        if (method.IsStatic)
        {
            return false;
        }

        return true;
    }

    /// <summary>
    /// 检查方法名是否匹配模式
    /// </summary>
    private bool IsMethodNameMatch(string methodName, string pattern)
    {
        if (pattern.EndsWith("*"))
        {
            return methodName.StartsWith(pattern[..^1], StringComparison.OrdinalIgnoreCase);
        }

        if (pattern.StartsWith("*"))
        {
            return methodName.EndsWith(pattern[1..], StringComparison.OrdinalIgnoreCase);
        }

        return string.Equals(methodName, pattern, StringComparison.OrdinalIgnoreCase);
    }

    /// <summary>
    /// 创建方法映射信息
    /// </summary>
    private ServiceMethodMapping CreateMethodMapping(MethodInfo method, string servicePrefix)
    {
        var mapping = new ServiceMethodMapping
        {
            MethodName = method.Name,
            HttpMethod = DetermineHttpMethod(method.Name),
            PathTemplate = CreatePathTemplate(method, servicePrefix),
            Description = $"Auto-generated endpoint for {method.Name}",
            ReturnType = method.ReturnType.Name,
            RequireAuthentication = _options.RequireAuthenticationByDefault,
            RequiredRoles = new List<string>(_options.DefaultRequiredRoles)
        };

        // 分析方法参数
        var parameters = method.GetParameters();
        foreach (var param in parameters)
        {
            if (param.ParameterType == typeof(CancellationToken))
                continue;

            var paramInfo = new MethodParameterInfo
            {
                Name = param.Name ?? "param",
                Type = param.ParameterType.Name,
                IsRequired = !param.HasDefaultValue,
                DefaultValue = param.HasDefaultValue ? param.DefaultValue : null,
                Source = DetermineParameterSource(param, mapping.HttpMethod)
            };

            mapping.Parameters.Add(paramInfo);
        }

        return mapping;
    }

    /// <summary>
    /// 确定HTTP方法
    /// </summary>
    private string DetermineHttpMethod(string methodName)
    {
        var lowerName = methodName.ToLowerInvariant();

        if (lowerName.StartsWith("get") || lowerName.StartsWith("list") || lowerName.StartsWith("search"))
            return "GET";

        if (lowerName.StartsWith("create") || lowerName.StartsWith("add"))
            return "POST";

        if (lowerName.StartsWith("update") || lowerName.StartsWith("modify"))
            return "PUT";

        if (lowerName.StartsWith("delete") || lowerName.StartsWith("remove"))
            return "DELETE";

        return "GET"; // 默认为GET
    }

    /// <summary>
    /// 创建路径模板
    /// </summary>
    private string CreatePathTemplate(MethodInfo method, string servicePrefix)
    {
        var basePath = $"{_options.BasePrefix}/{servicePrefix}";
        var methodName = method.Name;

        // 移除常见前缀
        var cleanMethodName = methodName;
        var prefixes = new[] { "Get", "Create", "Update", "Delete", "Search", "List" };

        foreach (var prefix in prefixes)
        {
            if (cleanMethodName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
            {
                cleanMethodName = cleanMethodName[prefix.Length..];
                break;
            }
        }

        // 如果方法有ID参数，添加到路径中
        var parameters = method.GetParameters();
        var idParam = parameters.FirstOrDefault(p =>
            p.Name?.Equals("id", StringComparison.OrdinalIgnoreCase) == true);

        if (idParam != null)
        {
            return $"{basePath}/{cleanMethodName.ToLowerInvariant()}/{{id}}";
        }

        return $"{basePath}/{cleanMethodName.ToLowerInvariant()}";
    }

    /// <summary>
    /// 确定参数来源
    /// </summary>
    private string DetermineParameterSource(ParameterInfo parameter, string httpMethod)
    {
        var paramName = parameter.Name?.ToLowerInvariant() ?? "";

        // ID参数通常来自路由
        if (paramName == "id")
        {
            return "Route";
        }

        // POST/PUT请求的复杂对象来自Body
        if ((httpMethod == "POST" || httpMethod == "PUT") &&
            !parameter.ParameterType.IsPrimitive &&
            parameter.ParameterType != typeof(string) &&
            parameter.ParameterType != typeof(Guid) &&
            parameter.ParameterType != typeof(DateTime))
        {
            return "Body";
        }

        // 其他参数来自Query
        return "Query";
    }

    /// <summary>
    /// 从映射信息创建端点
    /// </summary>
    private async Task<DynamicApiEndpoint?> CreateEndpointFromMapping(
        ServiceMethodMapping mapping,
        string serviceName,
        CancellationToken cancellationToken)
    {
        try
        {
            // 检查端点是否已存在
            var existingEndpoints = await _endpointRepository.GetByPathAndMethodAsync(
                mapping.PathTemplate, mapping.HttpMethod, null, cancellationToken);

            if (existingEndpoints.Any())
            {
                _logger.LogDebug("端点已存在: {Method} {Path}", mapping.HttpMethod, mapping.PathTemplate);
                return null;
            }

            var endpoint = new DynamicApiEndpoint
            {
                Name = $"{serviceName}.{mapping.MethodName}",
                Description = mapping.Description,
                Method = ConvertStringToHttpMethodEnum(mapping.HttpMethod),
                PathTemplate = mapping.PathTemplate,
                TargetService = serviceName,
                TargetUrl = null, // 内部服务调用
                IsEnabled = true,
                RequireAuthentication = false, // 开发环境默认不需要认证
                RequiredRoles = mapping.RequiredRoles,
                RequiredPermissions = new List<string>(),
                TimeoutSeconds = 30,
                RetryCount = 0,
                CacheSeconds = 0,
                Headers = new Dictionary<string, string>(),
                QueryParameters = new Dictionary<string, string>(),
                RequestTransformation = JsonSerializer.Serialize(mapping.Parameters),
                ResponseTransformation = null,
                Version = "1.0",
                Tags = new List<string> { "auto-generated", serviceName.ToLowerInvariant() },
                Priority = 0,
                Metadata = JsonSerializer.Serialize(new
                {
                    MethodName = mapping.MethodName,
                    ReturnType = mapping.ReturnType,
                    GeneratedAt = DateTime.UtcNow
                }),
                CreatedBy = "system",
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            return await _endpointRepository.CreateAsync(endpoint, cancellationToken);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "创建端点失败: {Method} {Path}", mapping.HttpMethod, mapping.PathTemplate);
            return null;
        }
    }

    /// <summary>
    /// 转换HTTP方法字符串为枚举值
    /// </summary>
    private int ConvertHttpMethodToEnum(string httpMethod)
    {
        return httpMethod.ToUpperInvariant() switch
        {
            "GET" => 0,
            "POST" => 1,
            "PUT" => 2,
            "DELETE" => 3,
            "PATCH" => 4,
            "HEAD" => 5,
            "OPTIONS" => 6,
            _ => 0
        };
    }

    /// <summary>
    /// 转换HTTP方法字符串为HttpMethod枚举
    /// </summary>
    private AuthService.Domain.Enums.HttpMethod ConvertStringToHttpMethodEnum(string httpMethod)
    {
        return AuthService.Domain.Enums.HttpMethodExtensions.FromString(httpMethod);
    }
}
